package com.findmeastore.action;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;

import com.findmeastore.Constents;
import com.findmeastore.bc.IBusinessDetailsBC;
import com.findmeastore.bo.BusinessAddress;
import com.findmeastore.bo.BusinessEntity;
import com.findmeastore.bo.CategoryBo;
import com.findmeastore.bo.ContactDetails;
import com.findmeastore.bo.StateBo;
import com.findmeastore.dto.BusinessDetailsDTO;
import com.findmeastore.dto.ContactDto;
import com.findmeastore.enums.Status;
import com.findmeastore.util.BeanCopyUtil;
import com.findmeastore.util.ValidateUtil;
import com.findmeastore.vo.CityVO;
import com.findmeastore.vo.LocalityVO;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import flexjson.JSONSerializer;

public class BusinessDetailsAction extends ActionSupport {

	private static final long serialVersionUID = 1L;
	private IBusinessDetailsBC businessDetailsBc ;
	private BusinessDetailsDTO businessDetailsDTO = new BusinessDetailsDTO();
	private List<CategoryBo> categoryList = new ArrayList<CategoryBo>();
	private Set<CategoryBo> selectedCategories = new HashSet<CategoryBo>();
	private List<CityVO> cityList = new ArrayList<CityVO>();
	private List<LocalityVO> localityList = new ArrayList<LocalityVO>();
	private List<StateBo> stateList = new ArrayList<StateBo>();
	private List<ContactDetails> contactsList = new ArrayList<ContactDetails>();
	private List<BusinessEntity> businessEntities = new ArrayList<BusinessEntity>();
	private String ind;
	private Integer businessId;
	private Status[] statuses = Status.values();
	
	private static final String SAVEBUSINESS = "saveBusiness"; 

	public String execute() {
		HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get( ServletActionContext.HTTP_REQUEST);
		HttpServletResponse response = (HttpServletResponse) ActionContext.getContext().get( ServletActionContext.HTTP_RESPONSE);
		String redirectionPath = "businessBasic";
		String indicator = request.getParameter("ind");
		String id = "";
		if(businessId != null && businessId > 0) {
			BusinessEntity business = businessDetailsBc.getBusinessById(businessId);
			if(business == null) {
				
				return INPUT;
			}
			businessDetailsDTO.setBusinessId(business.getId());
			businessDetailsDTO.setBusinessName(business.getName());
			Iterator itr = business.getBusinessAddresses().iterator();
			if(itr.hasNext()) {
				// right know application is not supported to add multiple address taking first one
				BusinessAddress address = (BusinessAddress)itr.next();
				businessDetailsDTO.setAddress1(address.getStreet1());
				businessDetailsDTO.setAddress2(address.getStreet2());
				businessDetailsDTO.setAddress3(address.getStreet3());
				Integer cityId = address.getCityId();
				Integer stateId = address.getStateId();
				businessDetailsDTO.setCity(String.valueOf(cityId));
				businessDetailsDTO.setState(String.valueOf(stateId));
				businessDetailsDTO.setPinCode(String.valueOf(address.getPinCode()));
				businessDetailsDTO.setLocalityId(address.getLocalityId());
			}
			List<ContactDto> contacts = new ArrayList<ContactDto>();
			Iterator contactItr = business.getContactDetailses().iterator();
			while(contactItr.hasNext()) {
				ContactDto contactDto = new ContactDto();
				ContactDetails contactDetails = (ContactDetails)contactItr.next();
				BeanCopyUtil.copy(contactDto, contactDetails);
				contactDto.setContactDetails(contactDetails.getConDetails());
				contacts.add(contactDto);
			}
			businessDetailsDTO.setContactList(contacts);
			selectedCategories = business.getCategory();
		}
		if("CITY".equals(indicator)){
			id = request.getParameter("id");
			response.setContentType("application/javascript");
			try {
				String cityJson = getCities(id);
				response.getWriter().write(cityJson);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}
		if("LOCALITY".equals(indicator)){
			id = request.getParameter("id");
			response.setContentType("application/javascript");
			try {
				response.getWriter().write(getLocalities(id));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}
		stateList = businessDetailsBc.getAllStates();
		categoryList = businessDetailsBc.getAllCategory();
		String state = businessDetailsDTO.getState();
		if(StringUtils.isNotEmpty(state)) {
				cityList =  businessDetailsBc.getCitiesByStateId(Integer.parseInt(state));
		}
		String city = businessDetailsDTO.getCity();
		if(StringUtils.isNotEmpty(city)) {
				localityList =  businessDetailsBc.getLocalitiesByCityId(Integer.parseInt(city));
		}
		return redirectionPath;
	}
	
	public String listBusiness(){
		setBusinessEntities(businessDetailsBc.getAllBusiness());
		return "success";
	}
	
	public String save(){
		businessDetailsDTO.setModifiedById(1);
		businessId = businessDetailsBc.saveBusinessEntity(businessDetailsDTO);
		businessDetailsDTO.setBusinessId(businessId);
		return "productAssociate";
	}
	
	public String getCities(String id){
		JSONSerializer jsonSer = new JSONSerializer();
		String jsonResult = null;
		try{
			cityList = businessDetailsBc.getCitiesByStateId(new Integer(id));
			jsonResult = jsonSer.serialize(cityList);
		}catch (Exception e) {
			e.printStackTrace();
		}
		return jsonResult;
	}

	public String getLocalities(String id){		
		JSONSerializer jsonSer = new JSONSerializer();
		String jsonResult = null;
		try{
			localityList = businessDetailsBc.getLocalitiesByCityId(new Integer(id));
			jsonResult = jsonSer.serialize(localityList);
		}catch (Exception e) {
			e.printStackTrace();
		}
		return jsonResult;
	}
	
	public void validate() {
		String actionName = ActionContext.getContext().getName();
		Map<String, List<String>> fieldErrorMap = new HashMap<String, List<String>>();
		super.setFieldErrors(fieldErrorMap);
		if(SAVEBUSINESS.equalsIgnoreCase(actionName)) {
			String businessName = businessDetailsDTO.getBusinessName();
			if(StringUtils.isEmpty(businessName)) {
				this.addFieldError(Constents.BUSINESSNAME, getText(Constents.ERROR_EMPTY, new String[]{getText(Constents.BUSINESSNAME)}));
			} else if(businessName.length() > 100) {
				this.addFieldError(Constents.BUSINESSNAME, getText(Constents.ERROR_MAX_LENGTH, new String[]{getText(Constents.BUSINESSNAME), "100"}));
			}
			String addressLine1 = businessDetailsDTO.getAddress1();
			if(StringUtils.isEmpty(addressLine1)) {
				this.addFieldError(Constents.ADDRESS_LINE1, getText(Constents.ERROR_EMPTY, new String[]{getText(Constents.ADDRESS_LINE1)}));
			}
			String pinCode = businessDetailsDTO.getPinCode();
			
			if(StringUtils.isEmpty(pinCode)) {
				this.addFieldError(Constents.PINCODE, getText(Constents.ERROR_EMPTY, new String[]{getText(Constents.PINCODE)}));
			}
			
			Integer locality = businessDetailsDTO.getLocalityId();
			if(locality == null || locality < 1) {
				this.addFieldError(Constents.LOCALITY, getText(Constents.ERROR_EMPTY, new String[]{getText(Constents.LOCALITY)}));
			}
			List<ContactDto> contacts = businessDetailsDTO.getContactList();
			if(CollectionUtils.isNotEmpty(contacts)) {
				int activePrimaryContact = 0;
				for(int i = 0; i < contacts.size(); i++) {
					String appendableString = "";
					ContactDto contactDto = contacts.get(i);
					String contactType = contactDto.getConType();
					if(StringUtils.isEmpty(contactType)) {
						this.addFieldError("contactType_"+i, getText(Constents.ERROR_EMPTY, new String[]{"Contact Type"}));
					} else {
						String contact = contactDto.getContactDetails();
						if(StringUtils.isEmpty(contact)) {
							this.addFieldError("contact_"+i, getText(Constents.ERROR_EMPTY, new String[]{"Contact Details"}));
						} else {
							if(contactType.equalsIgnoreCase("EMAIL")) {
								validateEmail(contact, i);
							} else if(contactType.equalsIgnoreCase("MOBILE")){
								if (!ValidateUtil.isValidMobile(contact)) {
									this.addFieldError("contact_"+i, getText(Constents.ERROR_INVALID, new String[]{"Mobile"}));
								}
							} else if(contactType.equalsIgnoreCase("TOLL-FREE")) {
								if (!ValidateUtil.isValidTollFree(contact)) {
									this.addFieldError("contact_"+i, getText(Constents.ERROR_INVALID, new String[]{"TOLL-FREE"}));
								}
							} 
							if (contactType.equalsIgnoreCase("PHONE") || contactType.equalsIgnoreCase("TELE-FAX") || contactType.equalsIgnoreCase("FAX")) {
								validatePhone(contact, i);
							}
							Status status = contactDto.getStatus();
							if ( status == null) {
								this.addFieldError("status_"+i, getText(Constents.ERROR_EMPTY, new String[]{"Status"}));
							}
							
							if(contactDto.isPrimary()) {
								activePrimaryContact += 1;
							}
						}
							
					}
				}
				
				if(activePrimaryContact == 0 || activePrimaryContact > 1) {
					this.addFieldError("isPrimary", "Please select one primary contact");
				}
			}			
			
			if(! fieldErrorMap.isEmpty()) {
				execute();
			}
		}
	}
	
	private void validateEmail(String contact, int index) {
		if (!ValidateUtil.isValidEmail(contact)) {
			this.addFieldError("contact_"+index, getText(Constents.ERROR_INVALID, new String[]{"Email"}));
		} else if (contact.trim().length() > 100) {
			this.addFieldError("contact_"+index, getText(Constents.ERROR_MAX_LENGTH, new String[]{"Email"}));
		}
	}
	
	private void validatePhone(String contact, int index){
		if(StringUtils.isEmpty(contact)){
			this.addFieldError("contact_"+index, getText(Constents.ERROR_INVALID, new String[]{"Contact"}));
		} else if (!ValidateUtil.isValidPhone(contact)) {
			this.addFieldError("contact_"+index, getText(Constents.ERROR_INVALID, new String[]{"Contact"}));
		}
	}

	private void validateStdCode(String stdCode, int index) {
			if (StringUtils.isEmpty(stdCode)) {
				this.addFieldError("contact_"+index, getText(Constents.ERROR_INVALID, new String[]{"Std Code"}));
			} else if (!ValidateUtil.isValidStdCode(stdCode)) {
				this.addFieldError("contact_"+index, getText(Constents.ERROR_INVALID, new String[]{"Std Code"}));
			}
	}

	public BusinessDetailsDTO getModel() {
		return businessDetailsDTO;
	}

	public void setBusinessDetailsBc(IBusinessDetailsBC businessDetailsBc) {
		this.businessDetailsBc = businessDetailsBc;
	}

	public IBusinessDetailsBC getBusinessDetailsBc() {
		return businessDetailsBc;
	}

	public BusinessDetailsDTO getBusinessDetailsDTO() {
		return businessDetailsDTO;
	}

	public void setBusinessDetailsDTO(BusinessDetailsDTO businessDetailsDTO) {
		this.businessDetailsDTO = businessDetailsDTO;
	}

	public List<CityVO> getCityList() {
		return cityList;
	}

	public void setCityList(List<CityVO> cityList) {
		this.cityList = cityList;
	}

	public List<LocalityVO> getLocalityList() {
		return localityList;
	}

	public void setLocalityList(List<LocalityVO> localityList) {
		this.localityList = localityList;
	}

	public List<StateBo> getStateList() {
		return stateList;
	}

	public void setStateList(List<StateBo> stateList) {
		this.stateList = stateList;
	}

	public void setContactsList(List<ContactDetails> contactsList) {
		this.contactsList = contactsList;
	}

	public List<ContactDetails> getContactsList() {
		return contactsList;
	}

	public List<CategoryBo> getCategoryList() {
		return categoryList;
	}

	public void setCategoryList(List<CategoryBo> categoryList) {
		this.categoryList = categoryList;
	}

	public List<BusinessEntity> getBusinessEntities() {
		return businessEntities;
	}

	public void setBusinessEntities(List<BusinessEntity> businessEntities) {
		this.businessEntities = businessEntities;
	}

	public void setBusinessId(Integer businessId) {
		this.businessId = businessId;
	}

	public Integer getBusinessId() {
		return businessId;
	}
	
	public String getInd() {
		return ind;
	}

	public void setInd(String ind) {
		this.ind = ind;
	}

	public Status[] getStatuses() {
		return statuses;
	}

	public void setStatuses(Status[] statuses) {
		this.statuses = statuses;
	}

	public Set<CategoryBo> getSelectedCategories() {
		return selectedCategories;
	}

	public void setSelectedCategories(Set<CategoryBo> selectedCategories) {
		this.selectedCategories = selectedCategories;
	}
}
